<?php

namespace maotool\office\xlsx;

use maotool\exception\RuntimeException;
use maotool\file\FileUtil;
use maotool\object\ObjUtil;
use maotool\object\ReflectionUtil;
use maotool\office\xls\Xls;

class Xlsx extends Xls
{

    /**
     * 名称
     * @var
     */
    protected $name;

    /**
     * 标题
     * @var
     */
    protected $title;

    /**
     * 密码
     * @var
     */
    protected $password;

    /**
     * @var Sheet[]
     */
    protected $sheets = [];

    public function __construct()
    {

    }

    /**
     * @return Sheet[]
     */
    public function getSheets()
    {
        return $this->sheets;
    }

    /**
     * @param Sheet[] $sheets
     */
    public function setSheets($sheets)
    {
        $this->sheets = $sheets;
    }


    /**
     * @return mixed
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param mixed $name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * @return mixed
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * @param mixed $title
     */
    public function setTitle($title)
    {
        $this->title = $title;
    }

    /**
     * @return mixed
     */
    public function getPassword()
    {
        return $this->password;
    }

    /**
     * @param mixed $password
     */
    public function setPassword($password)
    {
        $this->password = $password;
    }

    /**
     * 下载表格
     * @return void
     */
    public function download()
    {
        try {
            $spreadsheet = $this->getSpreadsheet();
            header('Content-Disposition: attachment;filename="' . $this->name . '.xlsx"');
            $writer = ReflectionUtil::method(["\PhpOffice\PhpSpreadsheet\IOFactory", "createWriter"], [$spreadsheet, ReflectionUtil::getConstant("\PhpOffice\PhpSpreadsheet\IOFactory", "READER_XLSX")]);
            /* @var \PhpOffice\PhpSpreadsheet\Writer\Xlsx $writer */
            @$writer->save('php://output');
            exit;
        } catch (\PhpOffice\PhpSpreadsheet\Writer\Exception $e) {
            throw new RuntimeException("表格下载失败");
        }
    }

    /**
     * 读取表格流
     * @return void
     */
    public function readerSpreadsheet($spreadsheet)
    {
        $worksheets = $spreadsheet->getAllSheets();
        foreach ($worksheets as $worksheet) {
            $isCreate = false;
            $sheet = $this->getSheetTitle($worksheet->getTitle());
            if (ObjUtil::isNull($sheet)) {
                $sheet = new Sheet();
                $sheet->title = $worksheet->getTitle();
                $isCreate = true;
            }
            $rows = [];
            foreach ($worksheet->getRowIterator() as $row) {
                $columns = [];
                $cellIterator = $row->getCellIterator();
                $cellIterator->setIterateOnlyExistingCells(false);
                foreach ($row->getCellIterator() as $cell) {
                    $columns[] = $cell->getValue();
                }
                $rows[] = $columns;
            }
            if (count($rows) > 0 && $sheet->getHeader() > 0) {
                $list = [];
                $mappers = [];
                foreach ($sheet->getHeader() as $headerKey => $headerValue) {
                    $isMapper = false;
                    foreach ($rows[0] as $index => $value) {
                        if ($headerValue == $value) {
                            $mappers[$index] = $headerKey;
                            $isMapper = true;
                        }
                    }
                    if (!$isMapper) {
                        $mappers[$headerKey] = $headerKey;
                    }
                }
                foreach (array_slice($rows, 1) as $row) {
                    $data = [];
                    foreach ($mappers as $mapperKey => $mapperValue) {
                        $data[$mapperValue] = $row[$mapperKey];
                    }
                    $list[] = $data;
                }
                $sheet->setList($list);
            }
            $sheet->setData($rows);
            $sheet->setTable($rows);
            if ($isCreate) {
                $this->sheets[] = $sheet;
            }
        }
    }

    /**
     * 读取表格流
     * @return void
     */
    public function readerStream($stream)
    {
        $reader = ReflectionUtil::instance('\PhpOffice\PhpSpreadsheet\Reader\Xlsx');
        /* @var \PhpOffice\PhpSpreadsheet\Reader\Xlsx $reader */
        try {
            $spreadsheet = $reader->load($stream);
            $this->readerSpreadsheet($spreadsheet);
        } catch (\PhpOffice\PhpSpreadsheet\Reader\Exception $e) {
            throw new RuntimeException("表格读取失败" . $e->getMessage());
        }
    }

    /**
     * 读取表格文件
     * @return void
     */
    public function readerFile($path)
    {
        $path = FileUtil::path($path);
        $reader = ReflectionUtil::instance('\PhpOffice\PhpSpreadsheet\Reader\Xlsx');
        /* @var \PhpOffice\PhpSpreadsheet\Reader\Xlsx $reader */
        try {
            $spreadsheet = $reader->load($path);
            $this->readerSpreadsheet($spreadsheet);
        } catch (\PhpOffice\PhpSpreadsheet\Reader\Exception $e) {
            throw new RuntimeException("表格读取失败" . $e->getMessage());
        }
    }

    /**
     * 获取表格
     * @param $title
     * @param $default
     * @return Sheet|null
     */
    public function getSheetTitle($title, $default = null)
    {
        foreach ($this->sheets as &$sheet) {
            return $sheet;
        }
        return $default;
    }

    /**
     * 保存为文件
     * @param string $path
     * @return string
     */
    public function writerFile($path)
    {
        try {
            $path = FileUtil::path($path);
            $spreadsheet = $this->getSpreadsheet();
            $writer = ReflectionUtil::instance('\PhpOffice\PhpSpreadsheet\Writer\Xlsx', [$spreadsheet]);
            /* @var \PhpOffice\PhpSpreadsheet\Writer\Xlsx $writer */
            @$writer->save($path);
            return $path;
        } catch (\PhpOffice\PhpSpreadsheet\Writer\Exception $e) {
            throw new RuntimeException("表格下载失败");
        }
    }

}